// Simple Single File XHR-Loader
/*
function XHR(){
	let request  = null;
	let callback = null;

	function load(url, type, done){
		if(request) abort();
		callback = done;
		type = type || "arraybuffer";

		request = new XMLHttpRequest();
		request.responseType = type;
		request.open("GET", url, true);
		request.onload = function() {
			callback && callback( request.response );
			request  = null;
			callback = null;
		}
		request.send();
	}

	function abort(){
		if(request){
			request.abort();
			request  = null;
			callback = null;
		}
	}

	return {
		load  : load,
		abort : abort
	}
}
*/

function XHR() {
	let request = null;
	let progress = 0;
	let finished = 0;
	let count = 0;
	let index = 0;

	const ratios = [];
	const results = [];

	function abort() {
		if (request) {
			request.abort();
			request = null;
		}
	}

	function startLoad(source, prog, done) {
		if (request) abort();

		const type = getType(getExt(source));
		request = new XMLHttpRequest();
		request.responseType = /(text|json)/gi.test(type) ? '' : type;
		request.open('GET', source, true);
		request.onprogress = (e) => {
			const p = e.loaded / e.total;
			if (ratios.length > 0) {
				const normalizedProgress = ratios[index];
				progress = finished + normalizedProgress * p;
			} else {
				progress = index / count + p / count;
			}

			// For whatever reason Infinity or NaN, pass 0. as default progress;

			progress = parseFloat(progress);
			progress = Number.isFinite(progress) ? progress : 0;
			prog && prog(progress);
		};

		request.onload = () => {
			let result;
			switch (type) {
				case 'text':
				default:
					result = request.responseText;
					break;
				case 'json':
					result = JSON.parse(request.responseText);
					break;
				case 'arraybuffer':
					result = request.response;
					break;
			}
			request = null;
			done(result);
		};
		request.send();
	}

	function getType(ext) {
		let type = '';
		switch (ext) {
			case 'txt':
			case 'obj':
				type = 'text';
				break;
			case 'json':
			case 'gltf':
				type = 'json';
				break;
			case 'bin':
			case 'glb':
			case 'dds':
			case 'pvr':
			default:
				type = 'arraybuffer';
				break;
		}
		return type;
	}

	function getExt(str) {
		return str
			.match(/\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/gim)[0]
			.replace(/\./, '')
			.toLowerCase();
	}

	function load(urls, prog, done) {
		index = 0;
		progress = 0;
		finished = 0;
		count = urls.length || 1;
		ratios.length = 0;
		results.length = 0;

		function queue() {
			let url;
			if (typeof urls[index] === 'string') {
				url = urls[index];
			} else {
				url = urls[index].src;
				ratios.push(parseFloat(urls[index].ratio || 1 / count));
			}
			startLoad(url, prog, (result) => {
				index++;
				if (ratios.length > 0) finished += ratios[index - 1];
				results.push(result);

				if (index < count) {
					queue();
				} else {
					done && done(results);
				}
			});
		}
		queue();
	}

	function loadFile(url, prog, done) {
		index = 0;
		progress = 0;
		finished = 0;
		count = 1;
		ratios.length = 0;
		results.length = 0;
		startLoad(url, prog, (result) => {
			done && done(result);
		});
	}

	return {
		load, // queue
		loadFile, // single
		abort
	};
}

export default XHR;
